{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Week 1 Day 5 - Business Brochure Generator (Community Contribution)\n",
        "\n",
        "This notebook implements a business solution that generates company brochures by:\n",
        "- Intelligently selecting relevant links using LLM\n",
        "- Aggregating content from multiple pages\n",
        "- Generating professional brochures with different styles\n",
        "- Supporting both OpenAI and Ollama models\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Setup complete!\n"
          ]
        }
      ],
      "source": [
        "# Setup and imports\n",
        "import os\n",
        "import json\n",
        "import requests\n",
        "from bs4 import BeautifulSoup\n",
        "from urllib.parse import urljoin\n",
        "from IPython.display import Markdown, display\n",
        "from openai import OpenAI\n",
        "from dotenv import load_dotenv\n",
        "\n",
        "load_dotenv(override=True)\n",
        "\n",
        "# Initialize OpenAI client\n",
        "openai = OpenAI()\n",
        "\n",
        "# Headers for web scraping\n",
        "HEADERS = {\n",
        "    \"User-Agent\": (\n",
        "        \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) \"\n",
        "        \"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\"\n",
        "    )\n",
        "}\n",
        "\n",
        "print(\"Setup complete!\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Web scraping utilities ready!\n"
          ]
        }
      ],
      "source": [
        "# Web scraping utilities\n",
        "def fetch_website_contents(url, char_limit=2000):\n",
        "    \"\"\"Fetch and clean website content\"\"\"\n",
        "    try:\n",
        "        response = requests.get(url, headers=HEADERS, timeout=10)\n",
        "        response.raise_for_status()\n",
        "        html = response.text\n",
        "    except Exception as e:\n",
        "        print(f\"Error fetching {url}: {e}\")\n",
        "        return f\"Error: Could not fetch website content\"\n",
        "\n",
        "    soup = BeautifulSoup(html, \"html.parser\")\n",
        "    \n",
        "    # Remove script and style elements\n",
        "    for script in soup([\"script\", \"style\"]):\n",
        "        script.decompose()\n",
        "    \n",
        "    title = soup.title.get_text(strip=True) if soup.title else \"No title found\"\n",
        "    text = soup.get_text()\n",
        "    \n",
        "    # Clean up whitespace\n",
        "    lines = (line.strip() for line in text.splitlines())\n",
        "    chunks = (phrase.strip() for line in lines for phrase in line.split(\"  \"))\n",
        "    text = ' '.join(chunk for chunk in chunks if chunk)\n",
        "    \n",
        "    return (f\"{title}\\\\n\\\\n{text}\").strip()[:char_limit]\n",
        "\n",
        "def fetch_website_links(url):\n",
        "    \"\"\"Fetch all links from a website\"\"\"\n",
        "    try:\n",
        "        response = requests.get(url, headers=HEADERS, timeout=10)\n",
        "        response.raise_for_status()\n",
        "        html = response.text\n",
        "    except Exception as e:\n",
        "        print(f\"Error fetching links from {url}: {e}\")\n",
        "        return []\n",
        "    \n",
        "    soup = BeautifulSoup(html, \"html.parser\")\n",
        "    links = []\n",
        "    \n",
        "    for a in soup.select(\"a[href]\"):\n",
        "        href = a.get(\"href\")\n",
        "        if href:\n",
        "            # Convert relative URLs to absolute\n",
        "            if href.startswith((\"http://\", \"https://\")):\n",
        "                links.append(href)\n",
        "            else:\n",
        "                links.append(urljoin(url, href))\n",
        "    \n",
        "    return list(set(links))  # Remove duplicates\n",
        "\n",
        "print(\"Web scraping utilities ready!\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Intelligent link selection ready!\n"
          ]
        }
      ],
      "source": [
        "# Intelligent link selection using LLM\n",
        "def select_relevant_links(url, model=\"gpt-4o-mini\"):\n",
        "    \"\"\"Use LLM to select relevant links for brochure generation\"\"\"\n",
        "    print(f\"🔍 Analyzing links for {url}...\")\n",
        "    \n",
        "    # Get all links\n",
        "    links = fetch_website_links(url)\n",
        "    print(f\"Found {len(links)} total links\")\n",
        "    \n",
        "    # Create prompt for link selection\n",
        "    link_system_prompt = \"\"\"\n",
        "    You are provided with a list of links found on a webpage.\n",
        "    You are able to decide which of the links would be most relevant to include in a brochure about the company,\n",
        "    such as links to an About page, or a Company page, or Careers/Jobs pages.\n",
        "    You should respond in JSON as in this example:\n",
        "\n",
        "    {\n",
        "        \"links\": [\n",
        "            {\"type\": \"about page\", \"url\": \"https://full.url/goes/here/about\"},\n",
        "            {\"type\": \"careers page\", \"url\": \"https://another.full.url/careers\"}\n",
        "        ]\n",
        "    }\n",
        "    \"\"\"\n",
        "    \n",
        "    user_prompt = f\"\"\"\n",
        "    Here is the list of links on the website {url} -\n",
        "    Please decide which of these are relevant web links for a brochure about the company, \n",
        "    respond with the full https URL in JSON format.\n",
        "    Do not include Terms of Service, Privacy, email links.\n",
        "\n",
        "    Links (some might be relative links):\n",
        "\n",
        "    {chr(10).join(links[:50])}  # Limit to first 50 links to avoid token limits\n",
        "    \"\"\"\n",
        "    \n",
        "    try:\n",
        "        response = openai.chat.completions.create(\n",
        "            model=model,\n",
        "            messages=[\n",
        "                {\"role\": \"system\", \"content\": link_system_prompt},\n",
        "                {\"role\": \"user\", \"content\": user_prompt}\n",
        "            ],\n",
        "            response_format={\"type\": \"json_object\"}\n",
        "        )\n",
        "        result = response.choices[0].message.content\n",
        "        links_data = json.loads(result)\n",
        "        print(f\"✅ Selected {len(links_data['links'])} relevant links\")\n",
        "        return links_data\n",
        "        \n",
        "    except Exception as e:\n",
        "        print(f\"❌ Error selecting links: {e}\")\n",
        "        return {\"links\": []}\n",
        "\n",
        "print(\"Intelligent link selection ready!\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Content aggregation ready!\n"
          ]
        }
      ],
      "source": [
        "# Content aggregation\n",
        "def fetch_page_and_all_relevant_links(url, model=\"gpt-4o-mini\"):\n",
        "    \"\"\"Fetch main page content and all relevant linked pages\"\"\"\n",
        "    print(f\"📄 Fetching content for {url}...\")\n",
        "    \n",
        "    # Get main page content\n",
        "    main_content = fetch_website_contents(url)\n",
        "    \n",
        "    # Get relevant links\n",
        "    relevant_links = select_relevant_links(url, model)\n",
        "    \n",
        "    # Build comprehensive content\n",
        "    result = f\"## Landing Page:\\\\n\\\\n{main_content}\\\\n## Relevant Links:\\\\n\"\n",
        "    \n",
        "    for link in relevant_links['links']:\n",
        "        print(f\"  📄 Fetching {link['type']}: {link['url']}\")\n",
        "        try:\n",
        "            content = fetch_website_contents(link[\"url\"])\n",
        "            result += f\"\\\\n\\\\n### Link: {link['type']}\\\\n\"\n",
        "            result += content\n",
        "        except Exception as e:\n",
        "            print(f\"    ❌ Error fetching {link['url']}: {e}\")\n",
        "            result += f\"\\\\n\\\\n### Link: {link['type']} (Error)\\\\n\"\n",
        "            result += f\"Error fetching content: {e}\"\n",
        "    \n",
        "    return result\n",
        "\n",
        "print(\"Content aggregation ready!\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Professional brochure generation ready!\n"
          ]
        }
      ],
      "source": [
        "# Professional brochure generation\n",
        "def create_company_brochure(company_name, url, model=\"gpt-4o-mini\", style=\"professional\"):\n",
        "    \"\"\"Generate a professional company brochure\"\"\"\n",
        "    print(f\"🏢 Creating brochure for {company_name}...\")\n",
        "    \n",
        "    # Get all content\n",
        "    all_content = fetch_page_and_all_relevant_links(url, model)\n",
        "    \n",
        "    # Truncate if too long (to avoid token limits)\n",
        "    if len(all_content) > 5000:\n",
        "        all_content = all_content[:5000] + \"\\\\n\\\\n[Content truncated...]\"\n",
        "    \n",
        "    # Define brochure system prompt based on style\n",
        "    if style == \"professional\":\n",
        "        brochure_system_prompt = \"\"\"\n",
        "        You are an assistant that analyzes the contents of several relevant pages from a company website\n",
        "        and creates a short brochure about the company for prospective customers, investors and recruits.\n",
        "        Respond in markdown without code blocks.\n",
        "        Include details of company culture, customers and careers/jobs if you have the information.\n",
        "        \"\"\"\n",
        "    elif style == \"humorous\":\n",
        "        brochure_system_prompt = \"\"\"\n",
        "        You are an assistant that analyzes the contents of several relevant pages from a company website\n",
        "        and creates a short, humorous, entertaining, witty brochure about the company for prospective customers, investors and recruits.\n",
        "        Respond in markdown without code blocks.\n",
        "        Include details of company culture, customers and careers/jobs if you have the information.\n",
        "        \"\"\"\n",
        "    else:\n",
        "        brochure_system_prompt = \"\"\"\n",
        "        You are an assistant that analyzes the contents of several relevant pages from a company website\n",
        "        and creates a short brochure about the company.\n",
        "        Respond in markdown without code blocks.\n",
        "        \"\"\"\n",
        "    \n",
        "    user_prompt = f\"\"\"\n",
        "    You are looking at a company called: {company_name}\n",
        "    Here are the contents of its landing page and other relevant pages;\n",
        "    use this information to build a short brochure of the company in markdown without code blocks.\n",
        "\n",
        "    {all_content}\n",
        "    \"\"\"\n",
        "    \n",
        "    try:\n",
        "        response = openai.chat.completions.create(\n",
        "            model=model,\n",
        "            messages=[\n",
        "                {\"role\": \"system\", \"content\": brochure_system_prompt},\n",
        "                {\"role\": \"user\", \"content\": user_prompt}\n",
        "            ],\n",
        "            temperature=0.7,\n",
        "            max_tokens=1000\n",
        "        )\n",
        "        brochure = response.choices[0].message.content\n",
        "        print(f\"✅ Brochure generated successfully!\")\n",
        "        return brochure\n",
        "        \n",
        "    except Exception as e:\n",
        "        print(f\"❌ Error generating brochure: {e}\")\n",
        "        return f\"Error generating brochure: {e}\"\n",
        "\n",
        "def display_brochure(company_name, url, model=\"gpt-4o-mini\", style=\"professional\"):\n",
        "    \"\"\"Display a company brochure\"\"\"\n",
        "    brochure = create_company_brochure(company_name, url, model, style)\n",
        "    display(Markdown(f\"# {company_name} Brochure\\\\n\\\\n{brochure}\"))\n",
        "\n",
        "print(\"Professional brochure generation ready!\")\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Testing brochure generation for Radio Africa Group...\n",
            "🏢 Creating brochure for Radio Africa Group...\n",
            "📄 Fetching content for https://radioafricagroup.co.ke/...\n",
            "🔍 Analyzing links for https://radioafricagroup.co.ke/...\n",
            "Found 34 total links\n",
            "✅ Selected 5 relevant links\n",
            "  📄 Fetching about page: https://staging.radioafrica.digital/about-us/\n",
            "  📄 Fetching case studies page: https://radioafricagroup.co.ke/case-studies\n",
            "  📄 Fetching contact page: https://radioafricagroup.co.ke/contact\n",
            "  📄 Fetching careers page: https://staging.radioafrica.digital/careers\n",
            "Error fetching https://staging.radioafrica.digital/careers: 404 Client Error: Not Found for url: https://staging.radioafrica.digital/careers\n",
            "  📄 Fetching services page: https://radioafricagroup.co.ke/services.html\n",
            "Error fetching https://radioafricagroup.co.ke/services.html: 404 Client Error: Not Found for url: https://radioafricagroup.co.ke/services.html\n",
            "✅ Brochure generated successfully!\n"
          ]
        },
        {
          "data": {
            "text/markdown": [
              "# Radio Africa Group Brochure\\n\\n# Radio Africa Group Brochure\n",
              "\n",
              "## About Us\n",
              "Radio Africa Group (RAG) is a leading media company based in Kenya, renowned for its diverse range of platforms that include six national radio stations, one television station, and a national newspaper. Our flagship brands such as Kiss FM, Classic 105, Radio Jambo, The Star newspaper, and Kiss TV reach millions of Kenyans daily, making us a cornerstone of the country's media landscape.\n",
              "\n",
              "At RAG, we pride ourselves on being at the forefront of Africa's marketing and communication industry. We are dedicated to innovation, creativity, and collaboration, striving to shape better futures through impactful storytelling and entertainment.\n",
              "\n",
              "## Our Mission\n",
              "We aim to amplify Kenyan voices, champion local talent, and deliver meaningful journalism that connects citizens to national conversations. With a focus on digital transformation and strategic partnerships, we are committed to leading the evolution of modern African media.\n",
              "\n",
              "## Company Culture\n",
              "At Radio Africa Group, our culture is built on creativity, collaboration, and a shared passion for media. We celebrate our employees' milestones, as seen in our recent surprise birthday celebration for CEO Martin Khafafa, fostering a family-like environment that values each individual's contribution. We believe in pushing boundaries and nurturing talent, creating a dynamic workplace where innovation thrives.\n",
              "\n",
              "## Our Audience\n",
              "Our diverse clientele includes listeners and viewers across Kenya, with a special focus on engaging younger audiences through music, talk shows, podcasts, and live streaming. We aim to build meaningful connections between brands and their target audiences, utilizing our deep insights and cutting-edge technology.\n",
              "\n",
              "## Careers at RAG\n",
              "We are always on the lookout for talented individuals who share our passion for media and innovation. Joining Radio Africa Group means becoming part of a vibrant team that values creativity, growth, and professional development. If you're interested in shaping the future of media in Africa, explore career opportunities with us!\n",
              "\n",
              "## Contact Us\n",
              "For inquiries, advertising opportunities, or to learn more about our services, reach out to us at:\n",
              "\n",
              "**Radio Africa Group**  \n",
              "Lion Place, Westlands  \n",
              "Nairobi, Kenya  \n",
              "Phone: +254 711 046200  \n",
              "Email: [info@radioafricagroup.co.ke](mailto:info@radioafricagroup.co.ke)  \n",
              "Operating Hours: Mon-Fri: 10:00 AM - 09:00 PM  \n",
              "\n",
              "Join us at Radio Africa Group, where we are transforming the media landscape and connecting communities across Kenya!"
            ],
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Test the brochure generator\n",
        "COMPANY_NAME = \"Radio Africa Group\"\n",
        "COMPANY_URL = \"https://radioafricagroup.co.ke/\"\n",
        "\n",
        "print(f\"Testing brochure generation for {COMPANY_NAME}...\")\n",
        "display_brochure(COMPANY_NAME, COMPANY_URL, style=\"professional\")\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": ".venv",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.12"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}
